/*********************************************************************************************************
**
**                                   GJB 标准测试集
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: gjb_S0102602AQ.c
**
** 文件创建日期: 2021 年 1 月 12 日
**
** 描        述: 验证优先级反转算法, 创建3个线程，优先级为 高 中 低, 低优先级线程先获得互斥锁, 中优先级线程开始运行, 一段时间
** 高优先级线程运行并尝试互斥锁，获取失败，低优先级线程开始运行(此时中优先级线程)
*********************************************************************************************************/
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h> 




#ifdef SYLIXOS
#define __SYLIXOS_KERNEL
#endif

//#include "gjb.h"

static pthread_mutex_t Amutex;
static pthread_barrier_t bt;
static pthread_t       thread_id1;
static pthread_t       thread_id2;
static pthread_t       thread_id3;
static pthread_attr_t  thread_attr1;
static pthread_attr_t  thread_attr2;
static pthread_attr_t  thread_attr3;

int pthread_delay(int ticks);

void *Fun1_2 (void *arg)
{
    volatile int i = 0, j = 0;
    int          res;

    bind(pthread_self(), 0);

    pthread_barrier_wait(&bt);

    printf("low-task is running\n");

    //获取互斥量A资源
   res = -100;
    res = pthread_mutex_lock(&Amutex);

    if (res == 0) {
        printf("low-task Get Amutex succesful\n");

    } else {
        printf("low-task Get Amutex Failed\n");
        return  ((void *)123);
    }

    printf("low-task Get Amutex and running\n");

    for (i = 0; i < 1000; i++) {
        for (j = 0; j < 100000; j++);
        for (j = 0; j < 1000000; j++);
        if (i % 100 == 0) {
            printf("low-task Get Amutex and running\n");
        }
    }

    res = -100;
    res = pthread_mutex_unlock(&Amutex); // 会有优先级恢复，所以会导致高优先级先打印释放锁成功
     if (res == 0) {
        printf("low-task Release Amutex succesful\n");

    } else {
        printf("low-task Release Amutex Failed\n");
        return  ((void *)123);
    }

    return NULL;
}

void *Fun2_2 (void *arg)
{
    volatile int i = 0, j = 0;

    bind(pthread_self(), 0);
    pthread_barrier_wait(&bt);

    printf("mid-task is running\n");

    pthread_delay(200); // 如果中优先级开始运行，我们推出保证第优先级先运行

  for (i = 0; i < 1000; i++) {
        for (j = 0; j < 100000; j++);
        for (j = 0; j < 10000; j++);
        if (i % 100 == 0) {
            printf("mid-task is running\n");
        }
    }

    return NULL;
}

void *Fun3_3 (void *arg)
{
    int     i = 0;
    int     res;

    bind(pthread_self(), 0);
    pthread_barrier_wait(&bt);

    printf("high-task is running\n");

    pthread_delay(800);        // 最高优先级让出CPU, 保证第优先级开始运行
    printf("high-task reques muext Amutex\n");

    //获取互斥量A资源
   res = -100;
    res = pthread_mutex_lock(&Amutex);
    if (res == 0) {
        printf("high-task Get Amutex succesful\n");

    } else {
        printf("high-task Get Amutex Failed\n");
    }

    for (i = 0; i < 10000; i++) {
        if (i % 100 == 0) {
            printf("high-task Get Amutex and running\n");
        }
    }

    res = -100;
    res = pthread_mutex_unlock(&Amutex);
    if (res == 0) {
        printf("high-task Release Amutex succesful\n");

    } else {
        printf("high-task Release Amutex Failed\n");
        return  ((void *)123);
    }

    return NULL;
}

//入口函数
int Test_S0102102AQ_1 (void)
{
    int status = -100;
    int nDelaytime = 2;        //延时2个ticks

    bind(pthread_self(), 0);

    pthread_barrier_init(&bt, NULL, 4);

    //互斥量初始化
    pthread_mutex_init(&Amutex, NULL);

    //创建任务
    pthread_attr_init(&thread_attr1);
    pthread_attr_init(&thread_attr2);
    pthread_attr_init(&thread_attr3);

    // thread_attr1.stackaddr = NULL;
    // thread_attr1.stacksize = PTHREAD_STACK_MIN * 2;
    // thread_attr1.inheritsched = PTHREAD_EXPLICIT_SCHED;
    // thread_attr1.schedpolicy = SCHED_RR;
    // thread_attr1.schedparam.sched_priority = 100;
    // thread_attr1.name = "low";

    // thread_attr2.stackaddr = NULL;
    // thread_attr2.stacksize = PTHREAD_STACK_MIN * 2;
    // thread_attr2.inheritsched = PTHREAD_EXPLICIT_SCHED;
    // thread_attr2.schedpolicy = SCHED_RR;
    // thread_attr2.schedparam.sched_priority = 110;
    // thread_attr2.name = "mid";

    // thread_attr3.stackaddr = NULL;
    // thread_attr3.stacksize = PTHREAD_STACK_MIN * 2;
    // thread_attr3.inheritsched = PTHREAD_EXPLICIT_SCHED;
    // thread_attr3.schedpolicy = SCHED_RR;
    // thread_attr3.schedparam.sched_priority = 120;
    // thread_attr3.name = "high";

    status = -100;

    status = pthread_create(&thread_id3, &thread_attr3, Fun3_3, NULL);
    if (status == 0) {
        printf("high-task create succesful\n");

    } else {
        printf("high-task create Failed\n");
        goto error;
    }
    //延时
    pthread_delay(nDelaytime);              // 2个ticks

    status = -100;

   status = pthread_create(&thread_id2, &thread_attr2, Fun2_2, NULL);
    if (status == 0) {
        printf("mid-task create succesful\n");

    } else {
        printf("mid-task create Failed\n");
        goto error;
    }

    //延时
    pthread_delay(nDelaytime);             // 2个ticks

    status = -100;

   status = pthread_create(&thread_id1, &thread_attr1, Fun1_2, NULL);
    if (status == 0) {
        printf("low-task create succesful\n");

    } else {
        printf("low-task create Failed\n");
        goto error;
    }


    pthread_barrier_wait(&bt);

    pthread_join(thread_id1, NULL);
    pthread_join(thread_id2, NULL);
    pthread_join(thread_id3, NULL);

    return  (0);

error:
    return  (-1);
}
/**********************************************************************
 * 函数名称： GJB_ENTRY()
 * 功能描述： 用户程序入口
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 无
 * 其它说明： 无
 **************************************************************************/
int main(int  argc, char **argv)
{
    int  result;

    result = Test_S0102102AQ_1();           /* security         */
    if (result != 0) {
        return (-1);
    }

    return (0);
}

typedef unsigned long long u64;
typedef	unsigned int 	u32;
#define SYSTEM_TICKS_USEC        1000
#define EMINITED 305
u64 g_pthread_delay_tick = 0;
int is_set_sys_rate = 0;
u32 g_sys_uleep_tick = 0;
int pthread_delay(int ticks)
{
    g_pthread_delay_tick = ticks;
    sched_yield();
    if(is_set_sys_rate)
    {
        return usleep(g_sys_uleep_tick * ticks);
    }
    else
    {
        return usleep(SYSTEM_TICKS_USEC * ticks);
    }
}
